import random
import copy


def two_points_cross(a1, a2):
    # 不改变原始数据进行操作
    a1_1 = copy.deepcopy(a1)
    a2_1 = copy.deepcopy(a2)
    # 交叉位置,point1<point2
    point1 = random.randint(0, len(a1_1))
    point2 = random.randint(0., len(a1_1))
    while point1 > point2 or point1 == point2:
        point1 = random.randint(0, len(a1_1))
        point2 = random.randint(0., len(a1_1))
    # 记录交叉项
    fragment1 = a1[point1:point2]
    fragment2 = a2[point1:point2]
    # 交叉
    a1_1[point1:point2], a2_1[point1:point2] = a2_1[point1:point2], a1_1[point1:point2]
    # 定义容器
    a1_2 = []  # 储存修正后的head
    a2_2 = []
    a1_3 = []  # 修正后的tail
    a2_3 = []
    # 子代1头部修正
    for i in a1_1[:point1]:
        while i in fragment2:
            i = fragment1[fragment2.index(i)]
        a1_2.append(i)
    # 子代2尾部修正
    for i in a1_1[point2:]:
        while i in fragment2:
            i = fragment1[fragment2.index(i)]
        a1_3.append(i)
    # 子代2头部修订
    for i in a2_1[:point1]:
        while i in fragment1:
            i = fragment2[fragment1.index(i)]
        a2_2.append(i)
    # 子代2尾部修订
    for i in a2_1[point2:]:
        while i in fragment1:
            i = fragment2[fragment1.index(i)]
        a2_3.append(i)

    child1 = a1_2 + fragment2 + a1_3
    child2 = a2_2 + fragment1 + a2_3
    # print('修正后的子代为:\n{}\n{}'.format(child1, child2))
    return child1, child2


# 将工作编码转化为工作任务（job_id,job_stage）
def code2JobStage(work_sequence):
    job_stage_list = []
    for job_stage_index, job_stage in enumerate(work_sequence):
        sub_work_sequence = work_sequence[0:job_stage_index]
        stage = 0
        for sub_val in sub_work_sequence:
            if (sub_val == job_stage):
                stage = stage + 1
            else:
                pass
        job_stage_list.append((job_stage, stage))
    return job_stage_list


# 将工作任务转化为不重复的字符串
def transformJobSeq2Unique(jobSeqModel, OtherSeq):
    model_dict_list = []
    model_seq_list = []
    for index, value in enumerate(jobSeqModel):
        temp = {'id': index, 'job_id': value[0], 'stage_id': value[1]}
        model_dict_list.append(temp)
        model_seq_list.append(index)

    other_seq_list = []
    for other_value in OtherSeq:
        other_value_job_id = other_value[0]
        other_value_stage_id = other_value[1]
        for model_dict in model_dict_list:
            if other_value_job_id == model_dict['job_id'] and other_value_stage_id == model_dict['stage_id']:
                other_seq_list.append(model_dict['id'])
                break
            else:
                pass
    return model_dict_list, model_seq_list, other_seq_list


# 将不重复的字符串编码为工作编码
def transformUnique2JobSeq2(model_dict_list, model_seq_list, other_seq_list):
    model_seq_transform_list = []
    for model_seq_value in model_seq_list:
        for model_dict in model_dict_list:
            if model_seq_value == model_dict['id']:
                model_seq_transform_list.append(model_dict['job_id'])
                break
            else:
                pass

    other_seq_transform_list = []
    for other_seq_value in other_seq_list:
        for model_dict in model_dict_list:
            if other_seq_value == model_dict['id']:
                other_seq_transform_list.append(model_dict['job_id'])
                break
            else:
                pass
    return model_seq_transform_list, other_seq_transform_list


# 两点交叉变异
def changeLocationMutation(seq):
    new_seq = seq.copy()
    point1 = random.randint(0, len(seq)-1)
    point2 = random.randint(0, len(seq)-1)
    char1 = new_seq[point1]
    char2 = new_seq[point2]
    new_seq[point1] = char2
    new_seq[point2] = char1
    return new_seq


if __name__ == '__main__':
    # a1 = random.sample(range(0, 10), 10)
    # a2 = random.sample(range(0, 10), 10)
    # print (a1,a2)
    # a1 = [3, 2, 0, 9, 7, 1, 5, 4, 6, 8]
    # a2 = [9, 6, 2, 8, 0, 3, 7, 4, 5, 1]
    # b1, b2 = two_points_cross(a1, a2)
    # print (b1)

    # PMX交叉
    # a1 = [0, 1, 1, 2, 0, 1, 2, 0, 2]
    # a1_seq = code2JobStage(a1)
    # a2 = [1, 1, 2, 2, 0, 1, 2, 0, 0]
    # a2_seq = code2JobStage(a2)
    # model_dict_list, model_seq_list, other_seq_list = transformJobSeq2Unique(a1_seq, a2_seq)
    # child1, child2 = two_points_cross(model_seq_list, other_seq_list)
    # model_seq_transform_list, other_seq_transform_list = transformUnique2JobSeq2(model_dict_list, child1, child2)
    # print (model_seq_transform_list, other_seq_transform_list)

    a1 = [3, 2, 0, 9, 7, 1, 5, 4, 6, 8]
    a2 = changeLocationMutation(a1)
    print(a1)
    pass
